package com.xuecheng.search.service;

import com.xuecheng.framework.domain.course.CoursePub;
import com.xuecheng.framework.domain.course.TeachplanMediaPub;
import com.xuecheng.framework.domain.search.CourseSearchParam;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 标题：
 * 作者：何处是归程
 * 时间：2020/3/7 - 20:34
 */
@Service
public class EsCourseService {
	@Value("${xuecheng.course.index}")
	private String index;
	@Value("${xuecheng.media.index}")
	private String media_index;
	@Value("${xuecheng.course.type}")
	private String type;
	@Value("${xuecheng.media.type}")
	private String media_type;
	@Value("${xuecheng.course.source_field}")
	private String source_field;
	@Value("${xuecheng.media.source_field}")
	private String media_source_field;
	@Autowired
	RestHighLevelClient highLevelClient;

	// 课程搜索
	public QueryResponseResult<CoursePub> list(int page, int size, CourseSearchParam courseSearchParam) {
		if (courseSearchParam == null) {
			courseSearchParam = new CourseSearchParam();
		}
		// 创建搜索请求对象
		SearchRequest searchRequest = new SearchRequest(index);
		// 设置搜索类型
		searchRequest.types(type);

		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		// 过虑字段
		String[] source_field_arr = source_field.split(",");
		searchSourceBuilder.fetchSource(source_field_arr, new String[]{});
		// 创建一个布尔查询对象
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		// 设置搜索条件
		// 根据关键字查询
		if (!StringUtils.isEmpty(courseSearchParam.getKeyword())) {
			MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(
					courseSearchParam.getKeyword(), "name", "description", "teachplan")
					.minimumShouldMatch("80%")
					.field("name", 10);
			boolQueryBuilder.must(multiMatchQueryBuilder);
		}
		// 根据一级分类
		if (!StringUtils.isEmpty(courseSearchParam.getMt())) {
			boolQueryBuilder.filter(QueryBuilders.termQuery("mt", courseSearchParam.getMt()));
		}
		// 根据二级分类
		if (!StringUtils.isEmpty(courseSearchParam.getSt())) {
			boolQueryBuilder.filter(QueryBuilders.termQuery("st", courseSearchParam.getSt()));
		}
		// 根据难度等级
		if (!StringUtils.isEmpty(courseSearchParam.getGrade())) {
			boolQueryBuilder.filter(QueryBuilders.termQuery("grade", courseSearchParam.getGrade()));
		}
		// 设置布尔查询到searchSourceBuilder
		searchSourceBuilder.query(boolQueryBuilder);
		// 设置分页参数
		if (page <= 0) {
			page = 1;
		}
		if (size <= 0) {
			size = 8;
		}
		searchSourceBuilder.from(page);
		searchSourceBuilder.size(size);
		// 设置高亮
		HighlightBuilder highlightBuilder = new HighlightBuilder();
		highlightBuilder.preTags("<font class='red'>");
		highlightBuilder.postTags("</font>");
		// 设置高亮字段
		highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
		searchSourceBuilder.highlighter(highlightBuilder);

		searchRequest.source(searchSourceBuilder);

		QueryResult<CoursePub> queryResult = new QueryResult<CoursePub>();
		List<CoursePub> coursePubs = new ArrayList<CoursePub>();
		try {
			// 执行搜索
			SearchResponse searchResponse = highLevelClient.search(searchRequest);
			// 获取响应结果
			SearchHits hits = searchResponse.getHits();
			// 总记录数
			long totalHits = hits.getTotalHits();
			queryResult.setTotal(totalHits);
			SearchHit[] searchHits = hits.getHits();
			for (SearchHit hit : searchHits) {
				CoursePub coursePub = new CoursePub();
				// 原文档
				Map<String, Object> sourceAsMap = hit.getSourceAsMap();
				// 取出ID
				String id = (String) sourceAsMap.get("id");
				coursePub.setId(id);
				// 取出name
				String name = (String) sourceAsMap.get("name");
				coursePub.setName(name);
				// 取出高亮字段
				Map<String, HighlightField> highlightFields = hit.getHighlightFields();
				if (highlightFields != null) {
					HighlightField highlightFieldName = highlightFields.get("name");
					if (highlightFieldName != null) {
						Text[] texts = highlightFieldName.fragments();
						StringBuffer sb = new StringBuffer();
						for (Text text : texts) {
							sb.append(text);
						}
						name = sb.toString();
						coursePub.setName(name);
					}
				}
				//图片
				String pic = (String) sourceAsMap.get("pic");
				coursePub.setPic(pic);
				//价格
				Double price = null;
				try {
					if (sourceAsMap.get("price") != null) {
						price = (Double) sourceAsMap.get("price");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				coursePub.setPrice(price);
				// 旧价格
				Double price_old = null;
				try {
					if (sourceAsMap.get("price_old") != null) {
						price_old = (Double) sourceAsMap.get("price_old");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				coursePub.setPrice_old(price_old);
				coursePubs.add(coursePub);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		queryResult.setList(coursePubs);
		return new QueryResponseResult<CoursePub>(CommonCode.SUCCESS, queryResult);
	}

	// 根据课程id查询课程信息
	public Map<String, CoursePub> getall(String id) {
		try {
			// 定义一个搜索请求对象
			SearchRequest searchRequest = new SearchRequest(index);
			// 指定type
			searchRequest.types(type);
			// 定义SearchSourceBuilder
			SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
			// 设置使用termQuery
			searchSourceBuilder.query(QueryBuilders.termQuery("id", id));
			searchRequest.source(searchSourceBuilder);
			SearchResponse search = highLevelClient.search(searchRequest);
			// 取出数据
			SearchHits hits = search.getHits();
			SearchHit[] searchHits = hits.getHits();
			Map<String, CoursePub> map = new HashMap<>();
			for (SearchHit searchHit : searchHits) {
				// 获取源文档的内容
				CoursePub coursePub = new CoursePub();
				Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
				String courseId = (String) sourceAsMap.get("id");
				String name = (String) sourceAsMap.get("name");
				String grade = (String) sourceAsMap.get("grade");
				String charge = (String) sourceAsMap.get("charge");
				String pic = (String) sourceAsMap.get("pic");
				String description = (String) sourceAsMap.get("description");
				String teachplan = (String) sourceAsMap.get("teachplan");
				coursePub.setId(courseId);
				coursePub.setName(name);
				coursePub.setPic(pic);
				coursePub.setCharge(charge);
				coursePub.setGrade(grade);
				coursePub.setTeachplan(teachplan);
				coursePub.setDescription(description);
				map.put(courseId, coursePub);
			}
			return map;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	// 根据多个课程计划ID查询课程媒资信息
	public QueryResponseResult<TeachplanMediaPub> getmedia(String[] teachplanIds) {
		try {
			// 定义一个搜索请求对象
			SearchRequest searchRequest = new SearchRequest(media_index);
			// 指定type
			searchRequest.types(media_type);
			// 定义SearchSourceBuilder
			SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
			// 设置使用termsQuery根据多个ID来查询
			searchSourceBuilder.query(QueryBuilders.termsQuery("teachplan_id", teachplanIds));
			// 过滤源字段
			String[] split = media_source_field.split(",");
			searchSourceBuilder.fetchSource(split, new String[]{});
			searchRequest.source(searchSourceBuilder);
			SearchResponse search = highLevelClient.search(searchRequest);
			// 取出数据
			SearchHits hits = search.getHits();
			// 总记录数
			long total = hits.totalHits;
			SearchHit[] searchHits = hits.getHits();
			List<TeachplanMediaPub> teachplanMediaPubList = new ArrayList<>();
			for (SearchHit hit : searchHits) {
				TeachplanMediaPub teachplanMediaPub = new TeachplanMediaPub();
				Map<String, Object> sourceAsMap = hit.getSourceAsMap();
				//取出课程计划媒资信息
				String courseid = (String) sourceAsMap.get("courseid");
				String media_id = (String) sourceAsMap.get("media_id");
				String media_url = (String) sourceAsMap.get("media_url");
				String teachplan_id = (String) sourceAsMap.get("teachplan_id");
				String media_fileoriginalname = (String) sourceAsMap.get("media_fileoriginalname");
				teachplanMediaPub.setCourseId(courseid);
				teachplanMediaPub.setMediaUrl(media_url);
				teachplanMediaPub.setMediaFileOriginalName(media_fileoriginalname);
				teachplanMediaPub.setMediaId(media_id);
				teachplanMediaPub.setTeachplanId(teachplan_id);
				//将数据加入列表
				teachplanMediaPubList.add(teachplanMediaPub);
			}
			QueryResult<TeachplanMediaPub> queryResult = new QueryResult<>();
			queryResult.setList(teachplanMediaPubList);
			queryResult.setTotal(total);
			return new QueryResponseResult<>(CommonCode.SUCCESS, queryResult);
		} catch (IOException e) {
			e.printStackTrace();
			return new QueryResponseResult<>(CommonCode.FAIL, null);
		}
	}
}
